package processes.nMCounterProcess;

import os.MiniSemaphore;

/**
 * The buffer to contain the count values
 */
public class Buffer
{
	/**
	 * The buffer size
	 */
	private int bufferSize;

	/**
	 * write end pointer
	 */
	private int in = 0;

	/**
	 * read end
	 */
	private int out = 0;

	/**
	 * The buffer
	 */
	private int[] buffer;

	/**
	 * Control access to the buffer
	 */
	private MiniSemaphore accessBuffer; // TODO make it minimutex

	/**
	 * The data controller
	 */
	private MiniSemaphore hasData;

	private boolean shouldTerminateMonitor;
	private boolean shouldTerminateCollector;

	/**
	 * Creates a buffer with a fixed size
	 * 
	 * @param bufferSize
	 * @param accessBuffer
	 */
	public Buffer(int bufferSize, MiniSemaphore accessBuffer)
	{
		this.bufferSize = bufferSize;
		this.buffer = new int[this.bufferSize];
		this.accessBuffer = accessBuffer;
		this.shouldTerminateMonitor = false;
		this.shouldTerminateCollector = false;
		this.hasData =  new MiniSemaphore(0);
	}

	public int get(int i)
	{
		return buffer[i];
	}

	public void set(int i, int data)
	{
		buffer[i] = data;
	}

	/**
	 * {@link MMonitorThread} will call it to get the value of the counts
	 * @param mMonitorThread
	 * @param result
	 */
	public void write(int result)
	{
		accessBuffer.P();
			buffer[in++] = result;
		accessBuffer.V();
		if (in == bufferSize)
			shouldTerminateMonitor = true;
		hasData.V();
	}


	/**
	 * {@link MCollectorThread} will call it to get the value of the counts 
	 * @param mCollectorThread
	 * @return the value buffered by the MMonitorThread
	 */
	public int read()
	{
		int result;
		hasData.P();
		accessBuffer.P();
			result = buffer[out++];
			if(out == bufferSize)
				shouldTerminateCollector = true;
		accessBuffer.V();
		return result;
	}

	public boolean shouldTerminateMonitor()
	{
		return shouldTerminateMonitor;
	}

	public boolean shouldTerminateCollector()
	{
		return shouldTerminateCollector;
	}
}